package tests

import java.math.*
import java.util.*
import kotlin.test.*
import org.testng.annotations.*

import com.chronoxor.proto.*
import com.chronoxor.proto.fbe.*
import com.chronoxor.test.*
import com.chronoxor.test.fbe.*

@Suppress("ReplaceAssertBooleanWithAssertEquality")
class TestSerialization
{
    @Test
    fun serializationDomain()
    {
        // Create a new account with some orders
        val account1 = Account(1, "Test", State.good, Balance("USD", 1000.0), Balance("EUR", 100.0), ArrayList())
        account1.orders.add(Order(1, "EURUSD", OrderSide.buy, OrderType.market, 1.23456, 1000.0))
        account1.orders.add(Order(2, "EURUSD", OrderSide.sell, OrderType.limit, 1.0, 100.0))
        account1.orders.add(Order(3, "EURUSD", OrderSide.buy, OrderType.stop, 1.5, 10.0))

        // Serialize the account to the FBE stream
        val writer = AccountModel()
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(account1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 252)

        // Deserialize the account from the FBE stream
        val account2 = Account()
        val reader = AccountModel()
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(account2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(account2.id, 1)
        assertEquals(account2.name, "Test")
        assertTrue(account2.state.hasFlags(State.good))
        assertEquals(account2.wallet.currency, "USD")
        assertEquals(account2.wallet.amount, 1000.0)
        assertNotEquals(account2.asset, null)
        assertEquals(account2.asset!!.currency, "EUR")
        assertEquals(account2.asset!!.amount, 100.0)
        assertEquals(account2.orders.size, 3)
        assertEquals(account2.orders[0].id, 1)
        assertEquals(account2.orders[0].symbol, "EURUSD")
        assertEquals(account2.orders[0].side, OrderSide.buy)
        assertEquals(account2.orders[0].type, OrderType.market)
        assertEquals(account2.orders[0].price, 1.23456)
        assertEquals(account2.orders[0].volume, 1000.0)
        assertEquals(account2.orders[1].id, 2)
        assertEquals(account2.orders[1].symbol, "EURUSD")
        assertEquals(account2.orders[1].side, OrderSide.sell)
        assertEquals(account2.orders[1].type, OrderType.limit)
        assertEquals(account2.orders[1].price, 1.0)
        assertEquals(account2.orders[1].volume, 100.0)
        assertEquals(account2.orders[2].id, 3)
        assertEquals(account2.orders[2].symbol, "EURUSD")
        assertEquals(account2.orders[2].side, OrderSide.buy)
        assertEquals(account2.orders[2].type, OrderType.stop)
        assertEquals(account2.orders[2].price, 1.5)
        assertEquals(account2.orders[2].volume, 10.0)
    }

    @Test
    fun serializationStructSimple()
    {
        // Create a new struct
        val struct1 = StructSimple()

        // Serialize the struct to the FBE stream
        val writer = StructSimpleModel()
        assertEquals(writer.model.fbeType, 110)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 392)

        // Deserialize the struct from the FBE stream
        val struct2 = StructSimple()
        val reader = StructSimpleModel()
        assertEquals(reader.model.fbeType, 110)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1, false)
        assertEquals(struct2.f2, true)
        assertEquals(struct2.f3, 0)
        assertEquals(struct2.f4, 0xFF.toByte())
        assertEquals(struct2.f5, '\u0000')
        assertEquals(struct2.f6, '!')
        assertEquals(struct2.f7, 0.toChar())
        assertEquals(struct2.f8, 0x0444.toChar())
        assertEquals(struct2.f9, 0)
        assertEquals(struct2.f10, 127)
        assertEquals(struct2.f11, 0u)
        assertEquals(struct2.f12, 0xFFu)
        assertEquals(struct2.f13, 0)
        assertEquals(struct2.f14, 32767)
        assertEquals(struct2.f15, 0u)
        assertEquals(struct2.f16, 0xFFFFu)
        assertEquals(struct2.f17, 0)
        assertEquals(struct2.f18, 2147483647)
        assertEquals(struct2.f19, 0u)
        assertEquals(struct2.f20, 0xFFFFFFFFu)
        assertEquals(struct2.f21, 0)
        assertEquals(struct2.f22, 9223372036854775807L)
        assertEquals(struct2.f23, 0u)
        assertEquals(struct2.f24, 0xFFFFFFFFFFFFFFFFuL)
        assertEquals(struct2.f25, 0.0f)
        assertTrue(Math.abs(struct2.f26 - 123.456f) < 0.0001)
        assertEquals(struct2.f27, 0.0)
        assertTrue(Math.abs(struct2.f28 - -123.567e+123) < 1e+123)
        assertEquals(struct2.f29, BigDecimal.valueOf(0))
        assertEquals(struct2.f30, BigDecimal.valueOf(123456.123456))
        assertEquals(struct2.f31, "")
        assertEquals(struct2.f32, "Initial string!")
        assertTrue(struct2.f33.epochSecond == 0L)
        assertTrue(struct2.f34.epochSecond == 0L)
        assertTrue(struct2.f35.epochSecond > GregorianCalendar(2018, 1, 1).toInstant().epochSecond)
        assertTrue(struct2.f36.compareTo(UUID(0, 0)) == 0)
        assertTrue(struct2.f37.compareTo(UUID(0, 0)) != 0)
        assertTrue(struct2.f38.compareTo(UUID.fromString("123e4567-e89b-12d3-a456-426655440000")) == 0)

        assertEquals(struct2.f1, struct1.f1)
        assertEquals(struct2.f2, struct1.f2)
        assertEquals(struct2.f3, struct1.f3)
        assertEquals(struct2.f4, struct1.f4)
        assertEquals(struct2.f5, struct1.f5)
        assertEquals(struct2.f6, struct1.f6)
        assertEquals(struct2.f7, struct1.f7)
        assertEquals(struct2.f8, struct1.f8)
        assertEquals(struct2.f9, struct1.f9)
        assertEquals(struct2.f10, struct1.f10)
        assertEquals(struct2.f11, struct1.f11)
        assertEquals(struct2.f12, struct1.f12)
        assertEquals(struct2.f13, struct1.f13)
        assertEquals(struct2.f14, struct1.f14)
        assertEquals(struct2.f15, struct1.f15)
        assertEquals(struct2.f16, struct1.f16)
        assertEquals(struct2.f17, struct1.f17)
        assertEquals(struct2.f18, struct1.f18)
        assertEquals(struct2.f19, struct1.f19)
        assertEquals(struct2.f20, struct1.f20)
        assertEquals(struct2.f21, struct1.f21)
        assertEquals(struct2.f22, struct1.f22)
        assertEquals(struct2.f23, struct1.f23)
        assertEquals(struct2.f24, struct1.f24)
        assertEquals(struct2.f25, struct1.f25)
        assertEquals(struct2.f26, struct1.f26)
        assertEquals(struct2.f27, struct1.f27)
        assertEquals(struct2.f28, struct1.f28)
        assertEquals(struct2.f29, struct1.f29)
        assertEquals(struct2.f30, struct1.f30)
        assertEquals(struct2.f31, struct1.f31)
        assertEquals(struct2.f32, struct1.f32)
        assertEquals(struct2.f33, struct1.f33)
        assertEquals(struct2.f34, struct1.f34)
        assertEquals(struct2.f35, struct1.f35)
        assertEquals(struct2.f36, struct1.f36)
        assertEquals(struct2.f37, struct1.f37)
        assertEquals(struct2.f38, struct1.f38)
        assertEquals(struct2.f39, struct1.f39)
        assertEquals(struct2.f40, struct1.f40)
    }

    @Test
    fun serializationStructOptional()
    {
        // Create a new struct
        val struct1 = StructOptional()

        // Serialize the struct to the FBE stream
        val writer = StructOptionalModel()
        assertEquals(writer.model.fbeType, 111)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 834)

        // Deserialize the struct from the FBE stream
        val struct2 = StructOptional()
        val reader = StructOptionalModel()
        assertEquals(reader.model.fbeType, 111)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1, false)
        assertEquals(struct2.f2, true)
        assertEquals(struct2.f3, 0)
        assertEquals(struct2.f4, 0xFF.toByte())
        assertEquals(struct2.f5, '\u0000')
        assertEquals(struct2.f6, '!')
        assertEquals(struct2.f7, 0.toChar())
        assertEquals(struct2.f8, 0x0444.toChar())
        assertEquals(struct2.f9, 0)
        assertEquals(struct2.f10, 127)
        assertEquals(struct2.f11, 0u)
        assertEquals(struct2.f12, 0xFFu)
        assertEquals(struct2.f13, 0)
        assertEquals(struct2.f14, 32767)
        assertEquals(struct2.f15, 0u)
        assertEquals(struct2.f16, 0xFFFFu)
        assertEquals(struct2.f17, 0)
        assertEquals(struct2.f18, 2147483647)
        assertEquals(struct2.f19, 0u)
        assertEquals(struct2.f20, 0xFFFFFFFFu)
        assertEquals(struct2.f21, 0)
        assertEquals(struct2.f22, 9223372036854775807L)
        assertEquals(struct2.f23, 0u)
        assertEquals(struct2.f24, 0xFFFFFFFFFFFFFFFFuL)
        assertEquals(struct2.f25, 0.0f)
        assertTrue(Math.abs(struct2.f26 - 123.456f) < 0.0001)
        assertEquals(struct2.f27, 0.0)
        assertTrue(Math.abs(struct2.f28 - -123.567e+123) < 1e+123)
        assertEquals(struct2.f29, BigDecimal.valueOf(0))
        assertEquals(struct2.f30, BigDecimal.valueOf(123456.123456))
        assertEquals(struct2.f31, "")
        assertEquals(struct2.f32, "Initial string!")
        assertTrue(struct2.f33.epochSecond == 0L)
        assertTrue(struct2.f34.epochSecond == 0L)
        assertTrue(struct2.f35.epochSecond > GregorianCalendar(2018, 1, 1).toInstant().epochSecond)
        assertTrue(struct2.f36.compareTo(UUID(0, 0)) == 0)
        assertTrue(struct2.f37.compareTo(UUID(0, 0)) != 0)
        assertTrue(struct2.f38.compareTo(UUID.fromString("123e4567-e89b-12d3-a456-426655440000")) == 0)

        assertEquals(struct2.f100, null)
        assertNotEquals(struct2.f101, null)
        assertEquals(struct2.f101!!, true)
        assertEquals(struct2.f102, null)
        assertEquals(struct2.f103, null)
        assertNotEquals(struct2.f104, null)
        assertEquals(struct2.f104!!, 0xFF.toByte())
        assertEquals(struct2.f105, null)
        assertEquals(struct2.f106, null)
        assertNotEquals(struct2.f107, null)
        assertEquals(struct2.f107!!, '!')
        assertEquals(struct2.f108, null)
        assertEquals(struct2.f109, null)
        assertNotEquals(struct2.f110, null)
        assertEquals(struct2.f110!!, 0x0444.toChar())
        assertEquals(struct2.f111, null)
        assertEquals(struct2.f112, null)
        assertNotEquals(struct2.f113, null)
        assertEquals(struct2.f113!!, 127)
        assertEquals(struct2.f114, null)
        assertEquals(struct2.f115, null)
        assertNotEquals(struct2.f116, null)
        assertEquals(struct2.f116!!, 0xFFu)
        assertEquals(struct2.f117, null)
        assertEquals(struct2.f118, null)
        assertNotEquals(struct2.f119, null)
        assertEquals(struct2.f119!!, 32767)
        assertEquals(struct2.f120, null)
        assertEquals(struct2.f121, null)
        assertNotEquals(struct2.f122, null)
        assertEquals(struct2.f122!!, 0xFFFFu)
        assertEquals(struct2.f123, null)
        assertEquals(struct2.f124, null)
        assertNotEquals(struct2.f125, null)
        assertEquals(struct2.f125!!, 2147483647)
        assertEquals(struct2.f126, null)
        assertEquals(struct2.f127, null)
        assertNotEquals(struct2.f128, null)
        assertEquals(struct2.f128!!, 0xFFFFFFFFu)
        assertEquals(struct2.f129, null)
        assertEquals(struct2.f130, null)
        assertNotEquals(struct2.f131, null)
        assertEquals(struct2.f131!!, 9223372036854775807L)
        assertEquals(struct2.f132, null)
        assertEquals(struct2.f133, null)
        assertNotEquals(struct2.f131, null)
        assertEquals(struct2.f134!!, 0xFFFFFFFFFFFFFFFFu)
        assertEquals(struct2.f135, null)
        assertEquals(struct2.f136, null)
        assertNotEquals(struct2.f137, null)
        assertTrue(Math.abs(struct2.f137!! - 123.456f) < 0.0001)
        assertEquals(struct2.f138, null)
        assertEquals(struct2.f139, null)
        assertNotEquals(struct2.f140, null)
        assertTrue(Math.abs(struct2.f140!! - -123.567e+123) < 1e+123)
        assertEquals(struct2.f141, null)
        assertEquals(struct2.f142, null)
        assertNotEquals(struct2.f143, null)
        assertEquals(struct2.f143, BigDecimal.valueOf(123456.123456))
        assertEquals(struct2.f144, null)
        assertEquals(struct2.f145, null)
        assertNotEquals(struct2.f146, null)
        assertEquals(struct2.f146, "Initial string!")
        assertEquals(struct2.f147, null)
        assertEquals(struct2.f148, null)
        assertNotEquals(struct2.f149, null)
        assertTrue(struct2.f149!!.epochSecond > GregorianCalendar(2018, 1, 1).toInstant().epochSecond)
        assertEquals(struct2.f150, null)
        assertEquals(struct2.f151, null)
        assertNotEquals(struct2.f152, null)
        assertTrue(struct2.f152!!.compareTo(UUID.fromString("123e4567-e89b-12d3-a456-426655440000")) == 0)
        assertEquals(struct2.f153, null)
        assertEquals(struct2.f154, null)
        assertEquals(struct2.f155, null)
        assertEquals(struct2.f156, null)
        assertEquals(struct2.f157, null)
        assertEquals(struct2.f158, null)
        assertEquals(struct2.f159, null)
        assertEquals(struct2.f160, null)
        assertEquals(struct2.f161, null)
        assertEquals(struct2.f162, null)
        assertEquals(struct2.f163, null)
        assertEquals(struct2.f164, null)
        assertEquals(struct2.f165, null)

        assertEquals(struct2.f1, struct1.f1)
        assertEquals(struct2.f2, struct1.f2)
        assertEquals(struct2.f3, struct1.f3)
        assertEquals(struct2.f4, struct1.f4)
        assertEquals(struct2.f5, struct1.f5)
        assertEquals(struct2.f6, struct1.f6)
        assertEquals(struct2.f7, struct1.f7)
        assertEquals(struct2.f8, struct1.f8)
        assertEquals(struct2.f9, struct1.f9)
        assertEquals(struct2.f10, struct1.f10)
        assertEquals(struct2.f11, struct1.f11)
        assertEquals(struct2.f12, struct1.f12)
        assertEquals(struct2.f13, struct1.f13)
        assertEquals(struct2.f14, struct1.f14)
        assertEquals(struct2.f15, struct1.f15)
        assertEquals(struct2.f16, struct1.f16)
        assertEquals(struct2.f17, struct1.f17)
        assertEquals(struct2.f18, struct1.f18)
        assertEquals(struct2.f19, struct1.f19)
        assertEquals(struct2.f20, struct1.f20)
        assertEquals(struct2.f21, struct1.f21)
        assertEquals(struct2.f22, struct1.f22)
        assertEquals(struct2.f23, struct1.f23)
        assertEquals(struct2.f24, struct1.f24)
        assertEquals(struct2.f25, struct1.f25)
        assertEquals(struct2.f26, struct1.f26)
        assertEquals(struct2.f27, struct1.f27)
        assertEquals(struct2.f28, struct1.f28)
        assertEquals(struct2.f29, struct1.f29)
        assertEquals(struct2.f30, struct1.f30)
        assertEquals(struct2.f31, struct1.f31)
        assertEquals(struct2.f32, struct1.f32)
        assertEquals(struct2.f33, struct1.f33)
        assertEquals(struct2.f34, struct1.f34)
        assertEquals(struct2.f35, struct1.f35)
        assertEquals(struct2.f36, struct1.f36)
        assertEquals(struct2.f37, struct1.f37)
        assertEquals(struct2.f38, struct1.f38)
        assertEquals(struct2.f39, struct1.f39)
        assertEquals(struct2.f40, struct1.f40)

        assertEquals(struct2.f100, struct1.f100)
        assertEquals(struct2.f101, struct1.f101)
        assertEquals(struct2.f102, struct1.f102)
        assertEquals(struct2.f103, struct1.f103)
        assertEquals(struct2.f104, struct1.f104)
        assertEquals(struct2.f105, struct1.f105)
        assertEquals(struct2.f106, struct1.f106)
        assertEquals(struct2.f107, struct1.f107)
        assertEquals(struct2.f108, struct1.f108)
        assertEquals(struct2.f109, struct1.f109)
        assertEquals(struct2.f110, struct1.f110)
        assertEquals(struct2.f111, struct1.f111)
        assertEquals(struct2.f112, struct1.f112)
        assertEquals(struct2.f113, struct1.f113)
        assertEquals(struct2.f114, struct1.f114)
        assertEquals(struct2.f115, struct1.f115)
        assertEquals(struct2.f116, struct1.f116)
        assertEquals(struct2.f117, struct1.f117)
        assertEquals(struct2.f118, struct1.f118)
        assertEquals(struct2.f119, struct1.f119)
        assertEquals(struct2.f120, struct1.f120)
        assertEquals(struct2.f121, struct1.f121)
        assertEquals(struct2.f122, struct1.f122)
        assertEquals(struct2.f123, struct1.f123)
        assertEquals(struct2.f124, struct1.f124)
        assertEquals(struct2.f125, struct1.f125)
        assertEquals(struct2.f126, struct1.f126)
        assertEquals(struct2.f127, struct1.f127)
        assertEquals(struct2.f128, struct1.f128)
        assertEquals(struct2.f129, struct1.f129)
        assertEquals(struct2.f130, struct1.f130)
        assertEquals(struct2.f131, struct1.f131)
        assertEquals(struct2.f132, struct1.f132)
        assertEquals(struct2.f133, struct1.f133)
        assertEquals(struct2.f134, struct1.f134)
        assertEquals(struct2.f135, struct1.f135)
        assertEquals(struct2.f136, struct1.f136)
        assertEquals(struct2.f137, struct1.f137)
        assertEquals(struct2.f138, struct1.f138)
        assertEquals(struct2.f139, struct1.f139)
        assertEquals(struct2.f140, struct1.f140)
        assertEquals(struct2.f141, struct1.f141)
        assertEquals(struct2.f142, struct1.f142)
        assertEquals(struct2.f143, struct1.f143)
        assertEquals(struct2.f144, struct1.f144)
        assertEquals(struct2.f145, struct1.f145)
        assertEquals(struct2.f146, struct1.f146)
        assertEquals(struct2.f147, struct1.f147)
        assertEquals(struct2.f148, struct1.f148)
        assertEquals(struct2.f149, struct1.f149)
        assertEquals(struct2.f150, struct1.f150)
        assertEquals(struct2.f151, struct1.f151)
        assertEquals(struct2.f152, struct1.f152)
        assertEquals(struct2.f153, struct1.f153)
        assertEquals(struct2.f154, struct1.f154)
        assertEquals(struct2.f155, struct1.f155)
        assertEquals(struct2.f156, struct1.f156)
        assertEquals(struct2.f157, struct1.f157)
    }

    @Test
    fun serializationStructNested()
    {
        // Create a new struct
        val struct1 = StructNested()

        // Serialize the struct to the FBE stream
        val writer = StructNestedModel()
        assertEquals(writer.model.fbeType, 112)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 2099)

        // Deserialize the struct from the FBE stream
        val struct2 = StructNested()
        val reader = StructNestedModel()
        assertEquals(reader.model.fbeType, 112)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1, false)
        assertEquals(struct2.f2, true)
        assertEquals(struct2.f3, 0)
        assertEquals(struct2.f4, 0xFF.toByte())
        assertEquals(struct2.f5, '\u0000')
        assertEquals(struct2.f6, '!')
        assertEquals(struct2.f7, 0.toChar())
        assertEquals(struct2.f8, 0x0444.toChar())
        assertEquals(struct2.f9, 0)
        assertEquals(struct2.f10, 127)
        assertEquals(struct2.f11, 0u)
        assertEquals(struct2.f12, 0xFFu)
        assertEquals(struct2.f13, 0)
        assertEquals(struct2.f14, 32767)
        assertEquals(struct2.f15, 0u)
        assertEquals(struct2.f16, 0xFFFFu)
        assertEquals(struct2.f17, 0)
        assertEquals(struct2.f18, 2147483647)
        assertEquals(struct2.f19, 0u)
        assertEquals(struct2.f20, 0xFFFFFFFFu)
        assertEquals(struct2.f21, 0)
        assertEquals(struct2.f22, 9223372036854775807L)
        assertEquals(struct2.f23, 0u)
        assertEquals(struct2.f24, 0xFFFFFFFFFFFFFFFFuL)
        assertEquals(struct2.f25, 0.0f)
        assertTrue(Math.abs(struct2.f26 - 123.456f) < 0.0001)
        assertEquals(struct2.f27, 0.0)
        assertTrue(Math.abs(struct2.f28 - -123.567e+123) < 1e+123)
        assertEquals(struct2.f29, BigDecimal.valueOf(0))
        assertEquals(struct2.f30, BigDecimal.valueOf(123456.123456))
        assertEquals(struct2.f31, "")
        assertEquals(struct2.f32, "Initial string!")
        assertTrue(struct2.f33.epochSecond == 0L)
        assertTrue(struct2.f34.epochSecond == 0L)
        assertTrue(struct2.f35.epochSecond > GregorianCalendar(2018, 1, 1).toInstant().epochSecond)
        assertTrue(struct2.f36.compareTo(UUID(0, 0)) == 0)
        assertTrue(struct2.f37.compareTo(UUID(0, 0)) != 0)
        assertTrue(struct2.f38.compareTo(UUID.fromString("123e4567-e89b-12d3-a456-426655440000")) == 0)

        assertEquals(struct2.f100, null)
        assertNotEquals(struct2.f101, null)
        assertEquals(struct2.f101!!, true)
        assertEquals(struct2.f102, null)
        assertEquals(struct2.f103, null)
        assertNotEquals(struct2.f104, null)
        assertEquals(struct2.f104!!, 0xFF.toByte())
        assertEquals(struct2.f105, null)
        assertEquals(struct2.f106, null)
        assertNotEquals(struct2.f107, null)
        assertEquals(struct2.f107!!, '!')
        assertEquals(struct2.f108, null)
        assertEquals(struct2.f109, null)
        assertNotEquals(struct2.f110, null)
        assertEquals(struct2.f110!!, 0x0444.toChar())
        assertEquals(struct2.f111, null)
        assertEquals(struct2.f112, null)
        assertNotEquals(struct2.f113, null)
        assertEquals(struct2.f113!!, 127)
        assertEquals(struct2.f114, null)
        assertEquals(struct2.f115, null)
        assertNotEquals(struct2.f116, null)
        assertEquals(struct2.f116!!, 0xFFu)
        assertEquals(struct2.f117, null)
        assertEquals(struct2.f118, null)
        assertNotEquals(struct2.f119, null)
        assertEquals(struct2.f119!!, 32767)
        assertEquals(struct2.f120, null)
        assertEquals(struct2.f121, null)
        assertNotEquals(struct2.f122, null)
        assertEquals(struct2.f122!!, 0xFFFFu)
        assertEquals(struct2.f123, null)
        assertEquals(struct2.f124, null)
        assertNotEquals(struct2.f125, null)
        assertEquals(struct2.f125!!, 2147483647)
        assertEquals(struct2.f126, null)
        assertEquals(struct2.f127, null)
        assertNotEquals(struct2.f128, null)
        assertEquals(struct2.f128!!, 0xFFFFFFFFu)
        assertEquals(struct2.f129, null)
        assertEquals(struct2.f130, null)
        assertNotEquals(struct2.f131, null)
        assertEquals(struct2.f131!!, 9223372036854775807L)
        assertEquals(struct2.f132, null)
        assertEquals(struct2.f133, null)
        assertNotEquals(struct2.f131, null)
        assertEquals(struct2.f134!!, 0xFFFFFFFFFFFFFFFFu)
        assertEquals(struct2.f135, null)
        assertEquals(struct2.f136, null)
        assertNotEquals(struct2.f137, null)
        assertTrue(Math.abs(struct2.f137!! - 123.456f) < 0.0001)
        assertEquals(struct2.f138, null)
        assertEquals(struct2.f139, null)
        assertNotEquals(struct2.f140, null)
        assertTrue(Math.abs(struct2.f140!! - -123.567e+123) < 1e+123)
        assertEquals(struct2.f141, null)
        assertEquals(struct2.f142, null)
        assertNotEquals(struct2.f143, null)
        assertEquals(struct2.f143, BigDecimal.valueOf(123456.123456))
        assertEquals(struct2.f144, null)
        assertEquals(struct2.f145, null)
        assertNotEquals(struct2.f146, null)
        assertEquals(struct2.f146, "Initial string!")
        assertEquals(struct2.f147, null)
        assertEquals(struct2.f148, null)
        assertNotEquals(struct2.f149, null)
        assertTrue(struct2.f149!!.epochSecond > GregorianCalendar(2018, 1, 1).toInstant().epochSecond)
        assertEquals(struct2.f150, null)
        assertEquals(struct2.f151, null)
        assertNotEquals(struct2.f152, null)
        assertTrue(struct2.f152!!.compareTo(UUID.fromString("123e4567-e89b-12d3-a456-426655440000")) == 0)
        assertEquals(struct2.f153, null)
        assertEquals(struct2.f154, null)
        assertEquals(struct2.f155, null)
        assertEquals(struct2.f156, null)
        assertEquals(struct2.f157, null)
        assertEquals(struct2.f158, null)
        assertEquals(struct2.f159, null)
        assertEquals(struct2.f160, null)
        assertEquals(struct2.f161, null)
        assertEquals(struct2.f162, null)
        assertEquals(struct2.f163, null)
        assertEquals(struct2.f164, null)
        assertEquals(struct2.f165, null)

        assertEquals(struct2.f1000, EnumSimple.ENUM_VALUE_0)
        assertEquals(struct2.f1001, null)
        assertEquals(struct2.f1002, EnumTyped.ENUM_VALUE_2)
        assertEquals(struct2.f1003, null)
        assertEquals(struct2.f1004, FlagsSimple.FLAG_VALUE_0)
        assertEquals(struct2.f1005, null)
        assertEquals(struct2.f1006, FlagsTyped.fromSet(EnumSet.of(FlagsTyped.FLAG_VALUE_2.value, FlagsTyped.FLAG_VALUE_4.value, FlagsTyped.FLAG_VALUE_6.value)))
        assertEquals(struct2.f1007, null)
        assertEquals(struct2.f1009, null)
        assertEquals(struct2.f1011, null)

        assertEquals(struct2.f1, struct1.f1)
        assertEquals(struct2.f2, struct1.f2)
        assertEquals(struct2.f3, struct1.f3)
        assertEquals(struct2.f4, struct1.f4)
        assertEquals(struct2.f5, struct1.f5)
        assertEquals(struct2.f6, struct1.f6)
        assertEquals(struct2.f7, struct1.f7)
        assertEquals(struct2.f8, struct1.f8)
        assertEquals(struct2.f9, struct1.f9)
        assertEquals(struct2.f10, struct1.f10)
        assertEquals(struct2.f11, struct1.f11)
        assertEquals(struct2.f12, struct1.f12)
        assertEquals(struct2.f13, struct1.f13)
        assertEquals(struct2.f14, struct1.f14)
        assertEquals(struct2.f15, struct1.f15)
        assertEquals(struct2.f16, struct1.f16)
        assertEquals(struct2.f17, struct1.f17)
        assertEquals(struct2.f18, struct1.f18)
        assertEquals(struct2.f19, struct1.f19)
        assertEquals(struct2.f20, struct1.f20)
        assertEquals(struct2.f21, struct1.f21)
        assertEquals(struct2.f22, struct1.f22)
        assertEquals(struct2.f23, struct1.f23)
        assertEquals(struct2.f24, struct1.f24)
        assertEquals(struct2.f25, struct1.f25)
        assertEquals(struct2.f26, struct1.f26)
        assertEquals(struct2.f27, struct1.f27)
        assertEquals(struct2.f28, struct1.f28)
        assertEquals(struct2.f29, struct1.f29)
        assertEquals(struct2.f30, struct1.f30)
        assertEquals(struct2.f31, struct1.f31)
        assertEquals(struct2.f32, struct1.f32)
        assertEquals(struct2.f33, struct1.f33)
        assertEquals(struct2.f34, struct1.f34)
        assertEquals(struct2.f35, struct1.f35)
        assertEquals(struct2.f36, struct1.f36)
        assertEquals(struct2.f37, struct1.f37)
        assertEquals(struct2.f38, struct1.f38)
        assertEquals(struct2.f39, struct1.f39)
        assertEquals(struct2.f40, struct1.f40)

        assertEquals(struct2.f100, struct1.f100)
        assertEquals(struct2.f101, struct1.f101)
        assertEquals(struct2.f102, struct1.f102)
        assertEquals(struct2.f103, struct1.f103)
        assertEquals(struct2.f104, struct1.f104)
        assertEquals(struct2.f105, struct1.f105)
        assertEquals(struct2.f106, struct1.f106)
        assertEquals(struct2.f107, struct1.f107)
        assertEquals(struct2.f108, struct1.f108)
        assertEquals(struct2.f109, struct1.f109)
        assertEquals(struct2.f110, struct1.f110)
        assertEquals(struct2.f111, struct1.f111)
        assertEquals(struct2.f112, struct1.f112)
        assertEquals(struct2.f113, struct1.f113)
        assertEquals(struct2.f114, struct1.f114)
        assertEquals(struct2.f115, struct1.f115)
        assertEquals(struct2.f116, struct1.f116)
        assertEquals(struct2.f117, struct1.f117)
        assertEquals(struct2.f118, struct1.f118)
        assertEquals(struct2.f119, struct1.f119)
        assertEquals(struct2.f120, struct1.f120)
        assertEquals(struct2.f121, struct1.f121)
        assertEquals(struct2.f122, struct1.f122)
        assertEquals(struct2.f123, struct1.f123)
        assertEquals(struct2.f124, struct1.f124)
        assertEquals(struct2.f125, struct1.f125)
        assertEquals(struct2.f126, struct1.f126)
        assertEquals(struct2.f127, struct1.f127)
        assertEquals(struct2.f128, struct1.f128)
        assertEquals(struct2.f129, struct1.f129)
        assertEquals(struct2.f130, struct1.f130)
        assertEquals(struct2.f131, struct1.f131)
        assertEquals(struct2.f132, struct1.f132)
        assertEquals(struct2.f133, struct1.f133)
        assertEquals(struct2.f134, struct1.f134)
        assertEquals(struct2.f135, struct1.f135)
        assertEquals(struct2.f136, struct1.f136)
        assertEquals(struct2.f137, struct1.f137)
        assertEquals(struct2.f138, struct1.f138)
        assertEquals(struct2.f139, struct1.f139)
        assertEquals(struct2.f140, struct1.f140)
        assertEquals(struct2.f141, struct1.f141)
        assertEquals(struct2.f142, struct1.f142)
        assertEquals(struct2.f143, struct1.f143)
        assertEquals(struct2.f144, struct1.f144)
        assertEquals(struct2.f145, struct1.f145)
        assertEquals(struct2.f146, struct1.f146)
        assertEquals(struct2.f147, struct1.f147)
        assertEquals(struct2.f148, struct1.f148)
        assertEquals(struct2.f149, struct1.f149)
        assertEquals(struct2.f150, struct1.f150)
        assertEquals(struct2.f151, struct1.f151)
        assertEquals(struct2.f152, struct1.f152)
        assertEquals(struct2.f153, struct1.f153)
        assertEquals(struct2.f154, struct1.f154)
        assertEquals(struct2.f155, struct1.f155)
        assertEquals(struct2.f156, struct1.f156)
        assertEquals(struct2.f157, struct1.f157)

        assertEquals(struct2.f1000, struct1.f1000)
        assertEquals(struct2.f1001, struct1.f1001)
        assertEquals(struct2.f1002, struct1.f1002)
        assertEquals(struct2.f1003, struct1.f1003)
        assertEquals(struct2.f1004, struct1.f1004)
        assertEquals(struct2.f1005, struct1.f1005)
        assertEquals(struct2.f1006, struct1.f1006)
        assertEquals(struct2.f1007, struct1.f1007)
    }

    @Test
    fun serializationStructBytes()
    {
        // Create a new struct
        val struct1 = StructBytes()
        struct1.f1 = "ABC".toByteArray()
        struct1.f2 = "test".toByteArray()

        // Serialize the struct to the FBE stream
        val writer = StructBytesModel()
        assertEquals(writer.model.fbeType, 120)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 49)

        // Deserialize the struct from the FBE stream
        val struct2 = StructBytes()
        val reader = StructBytesModel()
        assertEquals(reader.model.fbeType, 120)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1.size, 3)
        assertEquals(struct2.f1[0], 'A'.toByte())
        assertEquals(struct2.f1[1], 'B'.toByte())
        assertEquals(struct2.f1[2], 'C'.toByte())
        assertNotEquals(struct2.f2, null)
        assertEquals(struct2.f2!!.size, 4)
        assertEquals(struct2.f2!![0], 't'.toByte())
        assertEquals(struct2.f2!![1], 'e'.toByte())
        assertEquals(struct2.f2!![2], 's'.toByte())
        assertEquals(struct2.f2!![3], 't'.toByte())
        assertEquals(struct2.f3, null)
    }

    @Test
    fun serializationStructArray()
    {
        // Create a new struct
        val struct1 = StructArray()
        struct1.f1[0] = 48
        struct1.f1[1] = 65
        struct1.f2[0] = 97
        struct1.f2[1] = null
        struct1.f3[0] = "000".toByteArray()
        struct1.f3[1] = "AAA".toByteArray()
        struct1.f4[0] = "aaa".toByteArray()
        struct1.f4[1] = null
        struct1.f5[0] = EnumSimple.ENUM_VALUE_1
        struct1.f5[1] = EnumSimple.ENUM_VALUE_2
        struct1.f6[0] = EnumSimple.ENUM_VALUE_1
        struct1.f6[1] = null
        struct1.f7[0] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value))
        struct1.f7[1] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value))
        struct1.f8[0] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value))
        struct1.f8[1] = null
        struct1.f9[0] = StructSimple()
        struct1.f9[1] = StructSimple()
        struct1.f10[0] = StructSimple()
        struct1.f10[1] = null

        // Serialize the struct to the FBE stream
        val writer = StructArrayModel()
        assertEquals(writer.model.fbeType, 125)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 1290)

        // Deserialize the struct from the FBE stream
        val struct2 = StructArray()
        val reader = StructArrayModel()
        assertEquals(reader.model.fbeType, 125)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1.size, 2)
        assertEquals(struct2.f1[0], 48)
        assertEquals(struct2.f1[1], 65)
        assertEquals(struct2.f2.size, 2)
        assertEquals(struct2.f2[0], 97)
        assertEquals(struct2.f2[1], null)
        assertEquals(struct2.f3.size, 2)
        assertEquals(struct2.f3[0].size, 3)
        assertEquals(struct2.f3[0][0].toInt(), 48)
        assertEquals(struct2.f3[0][1].toInt(), 48)
        assertEquals(struct2.f3[0][2].toInt(), 48)
        assertEquals(struct2.f3[1].size, 3)
        assertEquals(struct2.f3[1][0].toInt(), 65)
        assertEquals(struct2.f3[1][1].toInt(), 65)
        assertEquals(struct2.f3[1][2].toInt(), 65)
        assertEquals(struct2.f4.size, 2)
        assertNotEquals(struct2.f4[0], null)
        assertEquals(struct2.f4[0]!!.size, 3)
        assertEquals(struct2.f4[0]!![0].toInt(), 97)
        assertEquals(struct2.f4[0]!![1].toInt(), 97)
        assertEquals(struct2.f4[0]!![2].toInt(), 97)
        assertEquals(struct2.f4[1], null)
        assertEquals(struct2.f5.size, 2)
        assertEquals(struct2.f5[0], EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f5[1], EnumSimple.ENUM_VALUE_2)
        assertEquals(struct2.f6.size, 2)
        assertEquals(struct2.f6[0], EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f6[1], null)
        assertEquals(struct2.f7.size, 2)
        assertEquals(struct2.f7[0], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f7[1], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value)))
        assertEquals(struct2.f8.size, 2)
        assertEquals(struct2.f8[0], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f8[1], null)
        assertEquals(struct2.f9.size, 2)
        assertEquals(struct2.f9[0].f2, true)
        assertEquals(struct2.f9[0].f12, 0xFFu)
        assertEquals(struct2.f9[0].f32, "Initial string!")
        assertEquals(struct2.f9[1].f2, true)
        assertEquals(struct2.f9[1].f12, 0xFFu)
        assertEquals(struct2.f9[1].f32, "Initial string!")
        assertEquals(struct2.f10.size, 2)
        assertNotEquals(struct2.f10[0], null)
        assertEquals(struct2.f10[0]!!.f2, true)
        assertEquals(struct2.f10[0]!!.f12, 0xFFu)
        assertEquals(struct2.f10[0]!!.f32, "Initial string!")
        assertEquals(struct2.f10[1], null)
    }

    @Test
    fun serializationStructVector()
    {
        // Create a new struct
        val struct1 = StructVector()
        struct1.f1.add(48.toByte())
        struct1.f1.add(65.toByte())
        struct1.f2.add(97.toByte())
        struct1.f2.add(null)
        struct1.f3.add("000".toByteArray())
        struct1.f3.add("AAA".toByteArray())
        struct1.f4.add("aaa".toByteArray())
        struct1.f4.add(null)
        struct1.f5.add(EnumSimple.ENUM_VALUE_1)
        struct1.f5.add(EnumSimple.ENUM_VALUE_2)
        struct1.f6.add(EnumSimple.ENUM_VALUE_1)
        struct1.f6.add(null)
        struct1.f7.add(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        struct1.f7.add(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value)))
        struct1.f8.add(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        struct1.f8.add(null)
        struct1.f9.add(StructSimple())
        struct1.f9.add(StructSimple())
        struct1.f10.add(StructSimple())
        struct1.f10.add(null)

        // Serialize the struct to the FBE stream
        val writer = StructVectorModel()
        assertEquals(writer.model.fbeType, 130)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 1370)

        // Deserialize the struct from the FBE stream
        val struct2 = StructVector()
        val reader = StructVectorModel()
        assertEquals(reader.model.fbeType, 130)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1.size, 2)
        assertEquals(struct2.f1[0].toInt(), 48)
        assertEquals(struct2.f1[1].toInt(), 65)
        assertEquals(struct2.f2.size, 2)
        assertEquals(struct2.f2[0], 97)
        assertEquals(struct2.f2[1], null)
        assertEquals(struct2.f3.size, 2)
        assertEquals(struct2.f3[0].size, 3)
        assertEquals(struct2.f3[0][0].toInt(), 48)
        assertEquals(struct2.f3[0][1].toInt(), 48)
        assertEquals(struct2.f3[0][2].toInt(), 48)
        assertEquals(struct2.f3[1].size, 3)
        assertEquals(struct2.f3[1][0].toInt(), 65)
        assertEquals(struct2.f3[1][1].toInt(), 65)
        assertEquals(struct2.f3[1][2].toInt(), 65)
        assertEquals(struct2.f4.size, 2)
        assertNotEquals(struct2.f4[0], null)
        assertEquals(struct2.f4[0]!!.size, 3)
        assertEquals(struct2.f4[0]!![0].toInt(), 97)
        assertEquals(struct2.f4[0]!![1].toInt(), 97)
        assertEquals(struct2.f4[0]!![2].toInt(), 97)
        assertEquals(struct2.f4[1], null)
        assertEquals(struct2.f5.size, 2)
        assertEquals(struct2.f5[0], EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f5[1], EnumSimple.ENUM_VALUE_2)
        assertEquals(struct2.f6.size, 2)
        assertEquals(struct2.f6[0], EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f6[1], null)
        assertEquals(struct2.f7.size, 2)
        assertEquals(struct2.f7[0], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f7[1], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value)))
        assertEquals(struct2.f8.size, 2)
        assertEquals(struct2.f8[0], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f8[1], null)
        assertEquals(struct2.f9.size, 2)
        assertEquals(struct2.f9[0].f2, true)
        assertEquals(struct2.f9[0].f12, 0xFFu)
        assertEquals(struct2.f9[0].f32, "Initial string!")
        assertEquals(struct2.f9[1].f2, true)
        assertEquals(struct2.f9[1].f12, 0xFFu)
        assertEquals(struct2.f9[1].f32, "Initial string!")
        assertEquals(struct2.f10.size, 2)
        assertNotEquals(struct2.f10[0], null)
        assertEquals(struct2.f10[0]!!.f2, true)
        assertEquals(struct2.f10[0]!!.f12, 0xFFu)
        assertEquals(struct2.f10[0]!!.f32, "Initial string!")
        assertEquals(struct2.f10[1], null)
    }

    @Test
    fun serializationStructList()
    {
        // Create a new struct
        val struct1 = StructList()
        struct1.f1.addLast(48.toByte())
        struct1.f1.addLast(65.toByte())
        struct1.f2.addLast(97.toByte())
        struct1.f2.addLast(null)
        struct1.f3.addLast("000".toByteArray())
        struct1.f3.addLast("AAA".toByteArray())
        struct1.f4.addLast("aaa".toByteArray())
        struct1.f4.addLast(null)
        struct1.f5.addLast(EnumSimple.ENUM_VALUE_1)
        struct1.f5.addLast(EnumSimple.ENUM_VALUE_2)
        struct1.f6.addLast(EnumSimple.ENUM_VALUE_1)
        struct1.f6.addLast(null)
        struct1.f7.addLast(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        struct1.f7.addLast(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value)))
        struct1.f8.addLast(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        struct1.f8.addLast(null)
        struct1.f9.addLast(StructSimple())
        struct1.f9.addLast(StructSimple())
        struct1.f10.addLast(StructSimple())
        struct1.f10.addLast(null)

        // Serialize the struct to the FBE stream
        val writer = StructListModel()
        assertEquals(writer.model.fbeType, 131)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 1370)

        // Deserialize the struct from the FBE stream
        val struct2 = StructList()
        val reader = StructListModel()
        assertEquals(reader.model.fbeType, 131)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1.size, 2)
        assertEquals(struct2.f1.first.toByte().toInt(), 48)
        assertEquals(struct2.f1.last.toByte().toInt(), 65)
        assertEquals(struct2.f2.size, 2)
        assertEquals(struct2.f2.first!!.toByte().toInt(), 97)
        assertEquals(struct2.f2.last, null)
        assertEquals(struct2.f3.size, 2)
        assertEquals(struct2.f3.first.size, 3)
        assertEquals(struct2.f3.first[0].toInt(), 48)
        assertEquals(struct2.f3.first[1].toInt(), 48)
        assertEquals(struct2.f3.first[2].toInt(), 48)
        assertEquals(struct2.f3.last.size, 3)
        assertEquals(struct2.f3.last[0].toInt(), 65)
        assertEquals(struct2.f3.last[1].toInt(), 65)
        assertEquals(struct2.f3.last[2].toInt(), 65)
        assertEquals(struct2.f4.size, 2)
        assertNotEquals(struct2.f4.first, null)
        assertEquals(struct2.f4.first!!.size, 3)
        assertEquals(struct2.f4.first!![0].toInt(), 97)
        assertEquals(struct2.f4.first!![1].toInt(), 97)
        assertEquals(struct2.f4.first!![2].toInt(), 97)
        assertEquals(struct2.f4.last, null)
        assertEquals(struct2.f5.size, 2)
        assertEquals(struct2.f5.first, EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f5.last, EnumSimple.ENUM_VALUE_2)
        assertEquals(struct2.f6.size, 2)
        assertEquals(struct2.f6.first, EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f6.last, null)
        assertEquals(struct2.f7.size, 2)
        assertEquals(struct2.f7.first, FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f7.last, FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value)))
        assertEquals(struct2.f8.size, 2)
        assertEquals(struct2.f8.first, FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f8.last, null)
        assertEquals(struct2.f9.size, 2)
        assertEquals(struct2.f9.first.f2, true)
        assertEquals(struct2.f9.first.f12, 0xFFu)
        assertEquals(struct2.f9.first.f32, "Initial string!")
        assertEquals(struct2.f9.last.f2, true)
        assertEquals(struct2.f9.last.f12, 0xFFu)
        assertEquals(struct2.f9.last.f32, "Initial string!")
        assertEquals(struct2.f10.size, 2)
        assertNotEquals(struct2.f10.first, null)
        assertEquals(struct2.f10.first!!.f2, true)
        assertEquals(struct2.f10.first!!.f12, 0xFFu)
        assertEquals(struct2.f10.first!!.f32, "Initial string!")
        assertEquals(struct2.f10.last, null)
    }

    @Test
    fun serializationStructSet()
    {
        // Create a new struct
        val struct1 = StructSet()
        struct1.f1.add(48.toByte())
        struct1.f1.add(65.toByte())
        struct1.f1.add(97.toByte())
        struct1.f2.add(EnumSimple.ENUM_VALUE_1)
        struct1.f2.add(EnumSimple.ENUM_VALUE_2)
        struct1.f3.add(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        struct1.f3.add(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value)))
        val s1 = StructSimple()
        s1.id = 48
        struct1.f4.add(s1)
        val s2 = StructSimple()
        s2.id = 65
        struct1.f4.add(s2)

        // Serialize the struct to the FBE stream
        val writer = StructSetModel()
        assertEquals(writer.model.fbeType, 132)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 843)

        // Deserialize the struct from the FBE stream
        val struct2 = StructSet()
        val reader = StructSetModel()
        assertEquals(reader.model.fbeType, 132)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1.size, 3)
        assertTrue(struct2.f1.contains(48.toByte()))
        assertTrue(struct2.f1.contains(65.toByte()))
        assertTrue(struct2.f1.contains(97.toByte()))
        assertEquals(struct2.f2.size, 2)
        assertTrue(struct2.f2.contains(EnumSimple.ENUM_VALUE_1))
        assertTrue(struct2.f2.contains(EnumSimple.ENUM_VALUE_2))
        assertEquals(struct2.f3.size, 2)
        assertTrue(struct2.f3.contains(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value))))
        assertTrue(struct2.f3.contains(FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value))))
        assertEquals(struct2.f4.size, 2)
        assertTrue(struct2.f4.contains(s1))
        assertTrue(struct2.f4.contains(s2))
    }

    @Test
    fun serializationStructMap()
    {
        // Create a new struct
        val struct1 = StructMap()
        struct1.f1[10] = 48.toByte()
        struct1.f1[20] = 65.toByte()
        struct1.f2[10] = 97.toByte()
        struct1.f2[20] = null
        struct1.f3[10] = "000".toByteArray()
        struct1.f3[20] = "AAA".toByteArray()
        struct1.f4[10] = "aaa".toByteArray()
        struct1.f4[20] = null
        struct1.f5[10] = EnumSimple.ENUM_VALUE_1
        struct1.f5[20] = EnumSimple.ENUM_VALUE_2
        struct1.f6[10] = EnumSimple.ENUM_VALUE_1
        struct1.f6[20] = null
        struct1.f7[10] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value))
        struct1.f7[20] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value))
        struct1.f8[10] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value))
        struct1.f8[20] = null
        val s1 = StructSimple()
        s1.id = 48
        struct1.f9[10] = s1
        val s2 = StructSimple()
        s2.id = 65
        struct1.f9[20] = s2
        struct1.f10[10] = s1
        struct1.f10[20] = null

        // Serialize the struct to the FBE stream
        val writer = StructMapModel()
        assertEquals(writer.model.fbeType, 140)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 1450)

        // Deserialize the struct from the FBE stream
        val struct2 = StructMap()
        val reader = StructMapModel()
        assertEquals(reader.model.fbeType, 140)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1.size, 2)
        assertEquals(struct2.f1[10]!!.toByte().toInt(), 48)
        assertEquals(struct2.f1[20]!!.toByte().toInt(), 65)
        assertEquals(struct2.f2.size, 2)
        assertEquals(struct2.f2[10]!!.toByte().toInt(), 97)
        assertEquals(struct2.f2[20], null)
        assertEquals(struct2.f3.size, 2)
        assertEquals(struct2.f3[10]!!.size, 3)
        assertEquals(struct2.f3[20]!!.size, 3)
        assertEquals(struct2.f4.size, 2)
        assertEquals(struct2.f4[10]!!.size, 3)
        assertEquals(struct2.f4[20], null)
        assertEquals(struct2.f5.size, 2)
        assertEquals(struct2.f5[10], EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f5[20], EnumSimple.ENUM_VALUE_2)
        assertEquals(struct2.f6.size, 2)
        assertEquals(struct2.f6[10], EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f6[20], null)
        assertEquals(struct2.f7.size, 2)
        assertEquals(struct2.f7[10], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f7[20], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value)))
        assertEquals(struct2.f8.size, 2)
        assertEquals(struct2.f8[10], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f8[20], null)
        assertEquals(struct2.f9.size, 2)
        assertEquals(struct2.f9[10]!!.id, 48)
        assertEquals(struct2.f9[20]!!.id, 65)
        assertEquals(struct2.f10.size, 2)
        assertEquals(struct2.f10[10]!!.id, 48)
        assertEquals(struct2.f10[20], null)
    }

    @Test
    fun serializationStructHash()
    {
        // Create a new struct
        val struct1 = StructHash()
        struct1.f1["10"] = 48.toByte()
        struct1.f1["20"] = 65.toByte()
        struct1.f2["10"] = 97.toByte()
        struct1.f2["20"] = null
        struct1.f3["10"] = "000".toByteArray()
        struct1.f3["20"] = "AAA".toByteArray()
        struct1.f4["10"] = "aaa".toByteArray()
        struct1.f4["20"] = null
        struct1.f5["10"] = EnumSimple.ENUM_VALUE_1
        struct1.f5["20"] = EnumSimple.ENUM_VALUE_2
        struct1.f6["10"] = EnumSimple.ENUM_VALUE_1
        struct1.f6["20"] = null
        struct1.f7["10"] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value))
        struct1.f7["20"] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value))
        struct1.f8["10"] = FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value))
        struct1.f8["20"] = null
        val s1 = StructSimple()
        s1.id = 48
        struct1.f9["10"] = s1
        val s2 = StructSimple()
        s2.id = 65
        struct1.f9["20"] = s2
        struct1.f10["10"] = s1
        struct1.f10["20"] = null

        // Serialize the struct to the FBE stream
        val writer = StructHashModel()
        assertEquals(writer.model.fbeType, 141)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 1570)

        // Deserialize the struct from the FBE stream
        val struct2 = StructHash()
        val reader = StructHashModel()
        assertEquals(reader.model.fbeType, 141)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1.size, 2)
        assertEquals(struct2.f1["10"]!!.toByte().toInt(), 48)
        assertEquals(struct2.f1["20"]!!.toByte().toInt(), 65)
        assertEquals(struct2.f2.size, 2)
        assertEquals(struct2.f2["10"]!!.toByte().toInt(), 97)
        assertEquals(struct2.f2["20"], null)
        assertEquals(struct2.f3.size, 2)
        assertEquals(struct2.f3["10"]!!.size, 3)
        assertEquals(struct2.f3["20"]!!.size, 3)
        assertEquals(struct2.f4.size, 2)
        assertEquals(struct2.f4["10"]!!.size, 3)
        assertEquals(struct2.f4["20"], null)
        assertEquals(struct2.f5.size, 2)
        assertEquals(struct2.f5["10"], EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f5["20"], EnumSimple.ENUM_VALUE_2)
        assertEquals(struct2.f6.size, 2)
        assertEquals(struct2.f6["10"], EnumSimple.ENUM_VALUE_1)
        assertEquals(struct2.f6["20"], null)
        assertEquals(struct2.f7.size, 2)
        assertEquals(struct2.f7["10"], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f7["20"], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value, FlagsSimple.FLAG_VALUE_3.value)))
        assertEquals(struct2.f8.size, 2)
        assertEquals(struct2.f8["10"], FlagsSimple.fromSet(EnumSet.of(FlagsSimple.FLAG_VALUE_1.value, FlagsSimple.FLAG_VALUE_2.value)))
        assertEquals(struct2.f8["20"], null)
        assertEquals(struct2.f9.size, 2)
        assertEquals(struct2.f9["10"]!!.id, 48)
        assertEquals(struct2.f9["20"]!!.id, 65)
        assertEquals(struct2.f10.size, 2)
        assertEquals(struct2.f10["10"]!!.id, 48)
        assertEquals(struct2.f10["20"], null)
    }

    @Test
    fun serializationStructHashExtended()
    {
        // Create a new struct
        val struct1 = StructHashEx()
        val s1 = StructSimple()
        s1.id = 48
        struct1.f1[s1] = StructNested()
        val s2 = StructSimple()
        s2.id = 65
        struct1.f1[s2] = StructNested()
        struct1.f2[s1] = StructNested()
        struct1.f2[s2] = null

        // Serialize the struct to the FBE stream
        val writer = StructHashExModel()
        assertEquals(writer.model.fbeType, 142)
        assertEquals(writer.model.fbeOffset, 4)
        val serialized = writer.serialize(struct1)
        assertEquals(serialized, writer.buffer.size)
        assertTrue(writer.verify())
        writer.next(serialized)
        assertEquals(writer.model.fbeOffset, 4 + writer.buffer.size)

        // Check the serialized FBE size
        assertEquals(writer.buffer.size, 7879)

        // Deserialize the struct from the FBE stream
        val struct2 = StructHashEx()
        val reader = StructHashExModel()
        assertEquals(reader.model.fbeType, 142)
        assertEquals(reader.model.fbeOffset, 4)
        reader.attach(writer.buffer)
        assertTrue(reader.verify())
        val deserialized = reader.deserialize(struct2)
        assertEquals(deserialized, reader.buffer.size)
        reader.next(deserialized)
        assertEquals(reader.model.fbeOffset, 4 + reader.buffer.size)

        assertEquals(struct2.f1.size, 2)
        assertEquals(struct2.f1[s1]!!.f1002, EnumTyped.ENUM_VALUE_2)
        assertEquals(struct2.f1[s2]!!.f1002, EnumTyped.ENUM_VALUE_2)
        assertEquals(struct2.f2.size, 2)
        assertEquals(struct2.f2[s1]!!.f1002, EnumTyped.ENUM_VALUE_2)
        assertEquals(struct2.f2[s2], null)
    }
}
